#include "Effect.h"
#include "Shader.h"
CEffect::CEffect( const char * pName )
:m_strName( pName )
{
}

CEffect::~CEffect(void)
{
}

// active the effect when draw the object
void CEffect::Activate()
{

}

// destroy the effect when quit the program
void CEffect::Destroy()
{

}

// from file or buid by youself
void CEffect::Create( CShader& pVertexShader, CShader & pFragmentShader, const char ** pAttribs, const char ** pUniforms )
{
	GLuint VertexHandle, FragmentHandle;

	if ( !CompileFromMemory( pVertexShader.GetSource(), GL_VERTEX_SHADER, VertexHandle ) )
	{
		printf( "Complile Shader Source Failed! \n");
		return;
	}

	if ( !CompileFromMemory( pFragmentShader.GetSource(), GL_FRAGMENT_SHADER, FragmentHandle ) )
	{
		glDeleteShader( VertexHandle );
		printf( "Error Fragment Shader \n ");
		return;
	}

	if ( !CreateProgram( VertexHandle, FragmentHandle ) )
	{
		printf("Compile The Program Failed! \n");
		return;
	}
}

// Load the vertex and fragment shader from the source
bool CEffect::CompileFromMemory( const char * pSource, GLenum eType, GLuint & iHandle )
{
	GLint iComplete;
	iHandle = glCreateShader( eType );
	if ( iHandle ==0 )
		return false;
	// load the source 
	glShaderSource( iHandle, 1, &pSource, NULL );

	// compile the shader
	glCompileShader( iHandle );
	
	// check the compile state;
	glGetShaderiv( iHandle, GL_COMPILE_STATUS, &iComplete );

	if( !iComplete )
	{
		GLint infoLen = 0;
		glGetShaderiv( iHandle, GL_INFO_LOG_LENGTH, &infoLen );

		if ( infoLen > 1 )
		{
			char * infoLog = (char*)malloc(sizeof(char) *infoLen );

			glGetShaderInfoLog( iHandle, infoLen, NULL, infoLog );
			printf( "Error Compile shader :%s\n", infoLog );
			free( infoLog );
		}
		glDeleteShader( iHandle );
		return false;
	}
	return true;
}

// Create And build the program
bool CEffect::CreateAndBuildProgram( GLuint iVertex, GLuint iFragment, const char ** pAttibs, const char ** pUniforms )
{
	return false;
}

// Create the program
bool CEffect::CreateProgram( GLuint iVertex, GLuint iFragment )
{
	m_uiProgram = glCreateProgram();
	if ( m_uiProgram == 0 )
		return false;

	glAttachShader( m_uiProgram, iVertex );
	glAttachShader( m_uiProgram, iFragment );

	glLinkProgram( m_uiProgram );
	
	GLint linked;
	glGetShaderiv( m_uiProgram, GL_LINK_STATUS, &linked );

	if ( !linked )
	{
		GLint infolen = 0;
		glGetProgramiv( m_uiProgram, GL_INFO_LOG_LENGTH, &infolen );
		if ( infolen > 1 )
		{
			char * infoLog = (char*)malloc(sizeof(char) *infolen );
			glGetProgramInfoLog( m_uiProgram, infolen, NULL, infoLog );
			printf("Error program linked failed: %s\n", infoLog );
			free( infoLog );
		}
		glDeleteProgram( m_uiProgram );
		return false;
	}
	glDeleteShader( iVertex );
	glDeleteShader( iFragment );
	return true;
}

// Build the program
bool CEffect::BuildProgram( const char ** pAttribs, const char ** pUniforms )
{
	if ( pAttribs == NULL || pUniforms == NULL )
	{
		printf("Error, Not Input The Attributes And Uniforms\n" );
		return false;
	}

	int nAttributes = sizeof(pAttribs)/sizeof(pAttribs[0]);
	for( int i = 0; i < nAttributes; ++i )
	{
		m_mapAttributs[pAttribs[i]] = -1;
	}

	int nUniforms = sizeof( pUniforms )/sizeof( pUniforms[0] );
	for( int i = 0; i < nUniforms; ++i )
	{
		m_mapUniforms[pUniforms[i]] = -1;
	}
	return false;
}

// LoadTextures from texture name
bool CEffect::LoadTextures( const char ** pTextures )
{
	return false;
}